package com.zonski.jbots.wireless.client;

import com.zonski.jbots.engine.*;
import com.zonski.jbots.game.JBotsEntityFactory;
import com.zonski.jbots.game.JBotsGameController;
import com.zonski.jbots.game.JBotsConstants;
import com.zonski.jbots.game.collision.ChargeSappingCollisionEffect;
import com.zonski.jbots.game.entity.InputMind;
import com.zonski.jbots.game.entity.BadBotMind;
import com.zonski.jbots.game.entity.MinimalInputMind;
import com.zonski.jbots.game.room.AsciiRoomFactory;

import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.lcdui.Display;
import javax.microedition.media.Manager;
import javax.microedition.media.Player;
import javax.microedition.media.MediaException;
import javax.microedition.media.control.ToneControl;
import java.util.Hashtable;
import java.util.Enumeration;
import java.io.InputStream;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/**
 * Created by IntelliJ IDEA.
 * User: Chris Glover
 * Date: Oct 29, 2003
 * Time: 11:15:13 AM
 * To change this template use Options | File Templates.
 */
public class JBotsMIDlet extends MIDlet implements Device
{
    private boolean paused;
    private boolean initialised;
    private WirelessEngineRunner engineRunner;
    private JBotsGameCanvas canvas;
    //private Hashtable players;
    private InputStreamFactory musicStreamFactory;

    private RoomRenderer roomRenderer;

    public static final String MAX_LEVEL_KEY = "max_level";
	
	private boolean sounds;

    public JBotsMIDlet()
    {
        //this.players = new Hashtable();
        /*
        String[] types = Manager.getSupportedContentTypes(null);
        for(int i=0; i<types.length; i++)
        {
            System.out.println(types[i]);
        }
        */
    }

    protected void destroyApp(boolean unconditional)
    {
        pauseApp();
        this.roomRenderer = null;
        this.paused = false;
        this.initialised = false;
        this.canvas = null;
        this.musicStreamFactory = null;
        this.engineRunner = null;
    }

    protected void startApp() throws MIDletStateChangeException
    {
        if(!initialised)
        {
            init();
            this.initialised = true;
        }else{
            Display.getDisplay(this).setCurrent(this.canvas);
        }
        if(this.paused)
        {
            paused = false;
            this.engineRunner.start();
        }
    }

    protected void pauseApp()
    {
        if(this.engineRunner.isRunning())
        {
            this.paused = true;
            this.engineRunner.stop();
        }
    }

    private void init()
        throws MIDletStateChangeException
    {
        try
        {
            Engine engine = new Engine(new JBotsEntityFactory(this), this);

            MinimalInputMind playerMind = new MinimalInputMind();
            engine.setMind(Engine.getPlayerMindName(0), playerMind);
            engine.setMind(Engine.getPlayerMindName(1), new BadBotMind(JBotsConstants.TANK_BOT));
            engine.setMind(Engine.getPlayerMindName(2), new BadBotMind(JBotsConstants.BABY_BOT));
            engine.setMind(Engine.getPlayerMindName(3), new BadBotMind(JBotsConstants.BOMB_BOT));

            RoomFactory roomFactory = new AsciiRoomFactory(new FileInputStreamFactory("/data/levels/", "lvl"));
            JBotsGameController controller = new JBotsGameController(engine, roomFactory);
            this.canvas = new JBotsGameCanvas(controller, this);
            this.canvas.setFullScreenMode(true);
            controller.setMode(JBotsGameController.LOADING);
            String maxLevelString = this.getAppProperty(MAX_LEVEL_KEY);
            controller.setMaxLevel(Integer.parseInt(maxLevelString));
            Display.getDisplay(this).setCurrent(canvas);
            this.roomRenderer = RoomRenderer.getRoomRenderer();
            this.canvas.setRoomRenderer(this.roomRenderer);

            this.engineRunner = new WirelessEngineRunner(controller, canvas, playerMind);
            controller.setEngineRunner(this.engineRunner);
            controller.setMode(JBotsGameController.INTRO);
            canvas.draw();
			
			this.sounds = "true".equals( this.getAppProperty( "sounds" ) );

            this.musicStreamFactory = new FileInputStreamFactory("/sounds/", "tone");
        }catch(Exception ex){
            ex.printStackTrace();
            throw new MIDletStateChangeException(ex.toString());
        }
    }

    // from device

    public final void vibrate(int duration)
    {
        //Display.getDisplay(this).vibrate(duration);
        this.canvas.shakeCycles = Math.max(this.canvas.shakeCycles, duration);
    }

    private Hashtable players = new Hashtable(20);

    private byte[] readSoundSequence(String sound)
        throws IOException
    {
        InputStream ins = this.musicStreamFactory.getInputStream(sound);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        int b;
        while((b = ins.read()) >= 0)
        {
            bos.write(b);
        }
        return bos.toByteArray();
    }

    public final void play(String sound, int times)
    {
		if( this.sounds )
		{
	        Player player = (Player)this.players.get(sound);
	        try
	        {
	            if(player == null)
	            {
	                byte[] sequence = readSoundSequence(sound);
	                player = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);
	                player.realize();

	                ToneControl c = (ToneControl)player.getControl("ToneControl");

	                c.setSequence(sequence);

	                this.players.put(sound, player);
	            }
	            if(player != null)
	            {
	                if(times == Device.LOOP)
	                {
	                    player.setLoopCount(-1);
	                    player.start();
	                }else if(times == Device.STOP){
	                    player.stop();
	                }else{
	                    if(times != 1)
	                    {
	                        player.setLoopCount(times);
	                    }
	                    player.start();
	                }
	            }
	        }catch(Exception ex){
	            System.err.println("unable to play "+sound);
	            //ex.printStackTrace();
	        }


        /*
        Player player = (Player)this.players.get(sound);
        try
        {
            if(player == null)
            {
                InputStream stream = musicStreamFactory.getInputStream(sound);

                player = Manager.createPlayer(stream, "audio/x-wav");
                player.realize();
                this.players.put(sound, player);
            }
            if(player != null)
            {
                if(times == Device.LOOP)
                {
                    player.setLoopCount(-1);
                    player.start();
                }else if(times == Device.STOP){
                    player.stop();
                }else{
                    if(times != 1)
                    {
                        player.setLoopCount(times);
                    }
                    player.start();
                }
            }
        }catch(Exception ex){
            System.err.println("error loading sound "+sound);
            ex.printStackTrace();
        }
        */


        // TODO : just use tones, music files are too expensive
        /*
        if(times == 1)
        {
            Object player = this.players.get(sound);
            if(player == null)
            {
                try
                {
                    InputStream stream = musicStreamFactory.getInputStream(sound);
                    player = Manager.createPlayer(stream, "audio/x-wav");
                }catch(Exception ex){
                    System.out.println("no player "+sound);
                    player = new Object();
                }
                this.players.put(sound, player);
            }
            if(player instanceof Player)
            {
                try
                {
                    ((Player)player).start();
                }catch(Exception ex){
                    ex.printStackTrace();
                }
            }
        }
        */
		}
    }

    public void stopAll()
    {
        this.roomRenderer.clear();
        Enumeration playerValues = this.players.elements();
        while(playerValues.hasMoreElements())
        {
            Object player = playerValues.nextElement();
            if(player instanceof Player)
            {
                try
                {
                    ((Player)player).stop();
                }catch(Exception ex){
                    ex.printStackTrace();
                }
            }
        }
    }
}
